<?php

namespace App\Http\Controllers\Payment;

use App\Http\Controllers\Controller;
use App\Jobs\OrderRefund;
use App\Models\Common\ApiResponse;
use App\Models\Common\BaseModel;
use App\Models\Common\Constant;
use App\Models\Payment\PaymentChannel;
use App\Models\Payment\PaymentOrder;
use App\Models\Payment\RefundOrder;
use Godruoyi\Snowflake\Snowflake;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;

class RefundController extends Controller
{

    public $name = '退款';

    public function index(Request $request)
    {
        $user = admin();

        $page = intval($request->get('page') ?: 1);
        $perPage = intval($request->get('per_page') ?: 10);

        $baseQuery = RefundOrder::with(['related', 'parkingLot:id,name'])->orderByDesc('updated_at');

        if ($parkingLotID = getParkingLotID(false, true)) {
            $baseQuery->where('parking_lot_id', $parkingLotID);
        } else {
            $baseQuery->whereIn('parking_lot_id', $user->parkingLotIds);
        }

        if ($refundStatus = $request->get('refund_status')) {
            $baseQuery->where('refund_status', $refundStatus);
        }

        if ($refundedAtBegan = $request->get('refunded_at_began')) {
            try {
                $refundedAtBegan = Carbon::parse($refundedAtBegan)->toDateTimeString();
                $baseQuery->where('created_at', '>=', $refundedAtBegan);
            } catch (\Throwable $exception) {
            }
        }

        if ($refundedAtEnded = $request->get('refunded_at_ended')) {
            try {
                $refundedAtEnded = Carbon::parse($refundedAtEnded)->toDateTimeString();
                $baseQuery->where('created_at', '<=', $refundedAtEnded);
            } catch (\Throwable $exception) {
            }
        }

//        $paginationDat = $baseQuery->paginate(intval($request->get('per_page')), '*', 'page', intval($request->get('page')));

        $paginationDat = BaseModel::getList($baseQuery, $page, $perPage);

        return ApiResponse::return('', $paginationDat);
    }

    public function export(Request $request)
    {
        $this->admin = $user = admin();

        $baseQuery = RefundOrder::query()->orderByDesc('updated_at');

        if ($parkingLotID = getParkingLotID(false, true)) {
            $baseQuery->where('parking_lot_id', $parkingLotID);
            $this->parkingLotID = $parkingLotID;
        } else {
            $baseQuery->whereIn('parking_lot_id', $user->parkingLotIds);
        }

        if ($refundStatus = $request->get('refund_status')) {
            $baseQuery->where('refund_status', $refundStatus);
        }

        if ($refundedAtBegan = $request->get('refunded_at_began')) {
            try {
                $refundedAtBegan = Carbon::parse($refundedAtBegan)->toDateTimeString();
                $baseQuery->where('refunded_at', '>=', $refundedAtBegan);
            } catch (\Throwable $exception) {
            }
        }

        if ($refundedAtEnded = $request->get('refunded_at_ended')) {
            try {
                $refundedAtEnded = Carbon::parse($refundedAtEnded)->toDateTimeString();
                $baseQuery->where('refunded_at', '<=', $refundedAtEnded);
            } catch (\Throwable $exception) {
            }
        }

        $this->logContent = '导出退款记录';

        $orders = $baseQuery->orderByDesc('id')->get();
        $fileType = 'xlsx';
        return fastexcel($orders->map(function ($order) {
            /** @var RefundOrder $order */
            $related = $order->related;
//            $carNo = optional($related)->car_no;
            $item = [
                '支付单号' => $order->paid_code,
                '订单抬头' => $related ? $related->order_title : '',
                '退款金额' => $order->getAsRefundAmountAttribute(),
                '支付方式' => $related ? $related->getAsPayTypeAttribute() : '',
                '退款时间' => $order->created_at ? \Carbon\Carbon::parse($order->created_at)->toDateTimeString() : '',
                '备注' => $order->remark,
                '退款状态' => $order->getAsRefundStatusAttribute(),
                '操作员' => $order->user_name,
            ];

            return $item;
        }))->download(storage_path(microtime(true) . '.' . $fileType));
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        //
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param \Illuminate\Http\Request $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        //
    }

    /**
     * Display the specified resource.
     *
     * @param int $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        //
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param int $id
     * @return \Illuminate\Http\Response
     */
    public function edit($id)
    {
        //
    }

    /**
     * Update the specified resource in storage.
     *
     * @param \Illuminate\Http\Request $request
     * @param int $id
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, $id)
    {
        //
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param int $id
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        //
    }

    public function toRefund(Request $request, string $orderPaidCode)
    {
        $this->admin = $user = admin();
        $this->parkingLotID = $parkingLotID = getParkingLotID();

        $paymentOrder = PaymentOrder::where('parking_lot_id', $parkingLotID)->where('paid_code', $orderPaidCode)->firstOrFail();
        $orderTitle = $paymentOrder->order_title;
        $remark = strval($request->get('remark'));

        if ($paymentOrder->order_status !== Constant::ORDER_STATUS_PAID) {
            throw new \InvalidArgumentException($orderTitle . '处于未支付状态');
        }

        if (!$paymentOrder->paid_at) {
            throw new \InvalidArgumentException($orderTitle . '处于未支付状态');
        }

        if (!$relatedOrder = $paymentOrder->related) {
            throw new \InvalidArgumentException($orderTitle . '关联的订单不存在或已被删除');
        }

        $refundAmount = $relatedOrder->final_amount;
        $refundBalanceAmount = 0;
        $refundPoint = 0;
        $refundPointAmount = $relatedOrder->refund_point_amount;

        if ($paymentOrder->amount !== $refundAmount) {
            throw new \InvalidArgumentException($orderTitle . '可退款金额不匹配');
        }

        $hadRefundedOrders = RefundOrder::query()->where('parking_lot_id', $parkingLotID)->where('paid_code', $relatedOrder->paid_code)->where('refund_status', RefundOrder::STATUS_SUCCESS)->get();

        if ($hadRefundedOrders->count()) {

            $refundAmount -= $hadRefundedOrders->sum('refund_amount');
            if ($refundAmount <= 0) {
                throw new \InvalidArgumentException('订单已退款');
            }
        }

        $snowflake = new Snowflake();

        $refundCode = $snowflake->id();

        if (PaymentChannel::CATEGORY_FUIOUPAY_AGGREGATE === optional($paymentOrder->paymentChannel)->category) {
            $parameters = $paymentOrder->paymentChannel->parameters ?: [];
            $orderPrefix = \Arr::get($parameters, 'order_prefix') ?: '';
            $refundCode = $orderPrefix . $refundCode;
        }

        $newRefundOrder = RefundOrder::create([
            'refund_code' => $refundCode,
            'paid_code' => $relatedOrder->paid_code,
            'refund_amount' => $refundAmount,
            'refund_balance_amount' => $refundBalanceAmount,
            'refund_point' => $refundPoint,
            'refund_status' => RefundOrder::STATUS_PENDING,
            'parking_lot_id' => $parkingLotID,
            'refund_type' => RefundOrder::REFUND_TYPE_ORIGINAL_RETURN,
            'user_id' => $user->id,
            'user_name' => $user->name,
            'remark' => $remark,
            'related_id' => $relatedOrder->id,
            'related_type' => get_class($relatedOrder),
            'payment_channel_id' => strval($paymentOrder->payment_channel_id)
        ]);

        $this->logContent = '发起退款申请['.$paymentOrder->order_title.']';

        OrderRefund::dispatch($newRefundOrder);
        return ApiResponse::return();
    }
}
